package com.dome.mvp.http;

import com.dome.mvp.MyApplication;
import com.dome.mvp.utils.DebugUtils;
import com.dome.mvp.utils.NetworkUtils;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Time: 6/1/2021 11:28
 * Author: TAO
 * Description:
 */
public class HttpClient {

    private static HttpClient instance = null;
    private RetrofitApi api;

    public static HttpClient getInstance() {
        if (instance == null) {
            synchronized (HttpClient.class) {
                if (instance == null) {
                    instance = new HttpClient();
                }
            }
        }
        return instance;
    }

    private HttpClient() {
        initRetrofit();
    }

    public static RetrofitApi getApi() {
        if (instance == null) {
            instance = getInstance();
        }
        return instance.api;
    }

    private void initRetrofit() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(DebugUtils::printfLog);
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient builder = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .addInterceptor(provideOfflineCacheInterceptor())
                .addNetworkInterceptor(provideCacheInterceptor())
                .cache(new Cache(MyApplication.getApp().getCacheDir(), 10 * 1024 * 1024))
                .connectTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .readTimeout(15, TimeUnit.SECONDS)
                .pingInterval(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .followRedirects(true)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("")
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(builder)
                .build();

        api = retrofit.create(RetrofitApi.class);
    }

    /**
     * 离线缓存
     *
     * @return 返回缓存拦截器
     */
    public Interceptor provideOfflineCacheInterceptor() {
        return chain -> {
            Request request = chain.request();
            // 未联网获取缓存数据
            if (NetworkUtils.isConnected()) {
                //在20秒缓存有效，此处测试用，实际根据需求设置具体缓存有效时间
                CacheControl build = new CacheControl.Builder()
                        .maxStale(20, TimeUnit.SECONDS)
                        .build();
                request = request.newBuilder()
                        .cacheControl(build)
                        .build();
            }
            return chain.proceed(request);
        };
    }

    /**
     * 有网络时在限定时间内多次请求取缓存，超过时间重新请求：
     * @return 返回缓存拦截器
     */
    public Interceptor provideCacheInterceptor() {
        return chain -> {
            Response proceed = chain.proceed(chain.request());
            // 正常访问同一请求接口（多次访问同一接口），给30秒缓存，超过时间重新发送请求，否则取缓存数据
            CacheControl cacheControl = new CacheControl.Builder()
                    .maxAge(30, TimeUnit.SECONDS)
                    .build();
            return proceed.newBuilder()
                    .header("cache_control", cacheControl.toString())
                    .build();
        };
    }


}
